package net.jonbuck.tassoo;

import net.jonbuck.tassoo.persistence.dao.TassooDao;
import net.jonbuck.tassoo.persistence.dao.TassooDaoImpl;

import org.apache.commons.lang.StringUtils;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tray;
import org.eclipse.swt.widgets.TrayItem;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.application.ActionBarAdvisor;
import org.eclipse.ui.application.IActionBarConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchWindowAdvisor;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.plugin.AbstractUIPlugin;

/**
 * 
 * 
 * @since 1.0.0
 */
public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {

	private IWorkbenchWindow window;

	private TrayItem trayItem;

	private Image trayImage;

	private IPreferencesService preferenceService;

	private final static String COMMAND_ID = "org.eclipse.ui.file.exit";

	/**
	 * 
	 * @param configurer
	 */
	public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
		super(configurer);
		preferenceService = Platform.getPreferencesService();
	}

	/**
     * 
     */
	public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) {
		return new ApplicationActionBarAdvisor(configurer);
	}

	/**
     * 
     */
	public void preWindowOpen() {
		IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
		configurer.setInitialSize(new Point(1024, 768));
		configurer.setShowCoolBar(true);
		configurer.setShowStatusLine(true);

		IPreferenceStore platformPreferences = PlatformUI.getPreferenceStore();
		platformPreferences.setValue(IWorkbenchPreferenceConstants.SHOW_TRADITIONAL_STYLE_TABS, false);

		TassooDao tassooDao = TassooDaoImpl.getInstance();
		if (preferenceService.getBoolean("net.jonbuck.tassoo", "automatic.task.store.open", false, null)) {
			String lastOpenedFile = preferenceService.getString("net.jonbuck.tassoo.persistence",
					"net.jonbuck.tassoo.lastfileopened", "", null);
			if (StringUtils.isNotBlank(lastOpenedFile)) {
				tassooDao.loadTaskStore(lastOpenedFile);
			}
		}
	}

	/**
     * 
     */
	public void postWindowCreate() {
		IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
		Display display = configurer.getWindow().getWorkbench().getDisplay();
		Shell shell = configurer.getWindow().getShell();

		IPreferencesService service = Platform.getPreferencesService();

		if (service.getBoolean("net.jonbuck.tassoo", "maximize.window", false, null)) {
			shell.setMaximized(true);
		} else {

			int nMinWidth = service.getInt("net.jonbuck.tassoo", "window.default.width", 1024, null);
			int nMinHeight = service.getInt("net.jonbuck.tassoo", "window.default.height", 768, null);

			Rectangle pDisplayBounds = display.getBounds();

			// This formulae calculate the shell's Left ant Top
			int nLeft = (pDisplayBounds.width - nMinWidth) / 2;
			int nTop = (pDisplayBounds.height - nMinHeight) / 2;

			// Set shell bounds,
			shell.setBounds(nLeft, nTop, nMinWidth, nMinHeight);
		}

	}

	/**
	 * 
	 */
	public void postWindowOpen() {
		super.postWindowOpen();

		if (preferenceService.getBoolean("net.jonbuck.tassoo", "minimize.application.system.tray", false, null)) {
			window = getWindowConfigurer().getWindow();
			initTaskItem(window);
			// Some OS might not support tray items
			if (trayItem != null) {
				minimizeBehavior();
				// Create exit and about action on the icon
				hookPopupMenu();
			}
		}		
	}

	// Add a listener to the shell

	private void minimizeBehavior() {
		window.getShell().addShellListener(new ShellAdapter() {
			// If the window is minimized hide the window
			public void shellIconified(ShellEvent e) {
				window.getShell().setVisible(false);
			}
		});
		// If user double-clicks on the tray icons the application will be
		// visible again
		trayItem.addListener(SWT.DefaultSelection, new Listener() {
			public void handleEvent(Event event) {
				Shell shell = window.getShell();
				if (!shell.isVisible()) {
					window.getShell().setMinimized(false);
					shell.setVisible(true);
				}
			}
		});
	}

	// We hook up on menu entry which allows to close the application
	private void hookPopupMenu() {
		trayItem.addListener(SWT.MenuDetect, new Listener() {
			public void handleEvent(Event event) {
				Menu menu = new Menu(window.getShell(), SWT.POP_UP);

				// Creates a new menu item that terminates the program
				// when selected
				MenuItem exit = new MenuItem(menu, SWT.NONE);
				exit.setText("Goodbye!");
				exit.addListener(SWT.Selection, new Listener() {
					public void handleEvent(Event event) {
						// Lets call our command
						IHandlerService handlerService = (IHandlerService) window.getService(IHandlerService.class);
						try {
							handlerService.executeCommand(COMMAND_ID, null);
						} catch (Exception ex) {
							throw new RuntimeException(COMMAND_ID);
						}
					}
				});
				// We need to make the menu visible
				menu.setVisible(true);
			}
		});
	}

	// This methods create the tray item and return a reference
	private TrayItem initTaskItem(IWorkbenchWindow window) {
		final Tray tray = window.getShell().getDisplay().getSystemTray();
		trayItem = new TrayItem(tray, SWT.NONE);
		trayImage = AbstractUIPlugin.imageDescriptorFromPlugin("net.jonbuck.tassoo.ui", "/icons/en16/bell.gif").createImage();
		trayItem.setImage(trayImage);
		trayItem.setToolTipText("Tassoo");
		return trayItem;

	}

	// We need to clean-up after ourself
	@Override
	public void dispose() {
		if (trayImage != null) {
			trayImage.dispose();
		}
		if (trayItem != null) {
			trayItem.dispose();
		}
	}

}
